%% -*- mode: erlang;erlang-indent-level: 2;indent-tabs-mode: nil -*-
%% vim: set ft=erlang ts=2 sw=2:

%% this code is not particularly nice.
%% the idea is to test for the presence of functions, in order to set
%% preprocessor flags, so that we can use the preprocessor to hide new
%% functions from old compilers.
%% "erl_opts" gets passed to the compiler.
%% "CONFIG" is a magic rebar thing.
%% The foldl takes a [{function(Predicate/0),atom(Macro)}].
%% If Predicate returns 'false', Macro is passed to the compiler.
%% Predicate should test for presence of new functions, and the Macro
%% should be used to enable old functions. That way new functions are
%% enabled by default.

CRYPTO =
{fun() -> code:ensure_loaded(crypto),
          erlang:function_exported(crypto,block_encrypt,4)
 end,
 'USE_PRE_R16_CRYPTO'},

NOW =
 {fun() -> erlang:is_builtin(erlang,timestamp,0)
  end,
  'USE_NOW'},

Checks = [CRYPTO, NOW],

%% ================================================
KeyAppend = fun(Tag,[],E,_)          -> [{Tag,[E]}];
               (Tag,[{Tag,O}|T],E,_) -> [{Tag,[E|O]}|T];
               (Tag,[H|T],E,G)       -> [H|G(Tag,T,E,G)]
end,

Check = fun(CFG,Predicate,Macro) ->
            case Predicate() of
              false -> KeyAppend(erl_opts,CFG,{d,Macro},KeyAppend);
              true  -> CFG
            end
        end,

lists:foldl(
  fun({Predicate,Macro},Cfg) -> Check(Cfg,Predicate,Macro) end,
  CONFIG,
  Checks).
